﻿using Engine.Graphics;
using Engine;
using Game;
using GameEntitySystem;
using System;
using TemplatesDatabase;

namespace JackODummy
{
	public class ComponentJackODummyModel : ComponentModel, IUpdateable
	{
		public ComponentJackODummy ComponentJackODummy
		{
			get; set;
		}
		public ComponentSpawn ComponentSpawn
		{
			get; set;
		}
		public UpdateOrder UpdateOrder => UpdateOrder.Default;

		ModelBone m_bottomBone, m_stickBone, m_bodyBone, m_headBone, m_armBone, m_hatBone;
		Vector2 m_headRotation;
		Vector3 m_bodyOffset;
		float m_stickRotation;
		double stickSwayStartTime, hitSwayStartTime;
		float stickSwayStartAngle;

		public void Update(float dt)
		{
			Vector2 headRotateOrder = ComponentJackODummy.StunTime > 0 ? new Vector2(12f, 20f) : Vector2.Zero;
			m_headRotation = Vector2.Lerp(m_headRotation, headRotateOrder, MathUtils.Saturate(15f * dt));
			if (ComponentJackODummy.ImpulseOrder != 0)
			{
				float f = MathUtils.Saturate(15f * dt);
				float angleOrder = MathUtils.Min(45f, ComponentJackODummy.ImpulseOrder * 1.5f);
				m_stickRotation = MathUtils.Lerp(m_stickRotation, angleOrder, f);
				if (MathF.Abs(angleOrder - m_stickRotation) <= 2f * f)
				{
					m_stickRotation = angleOrder;
					ComponentJackODummy.ImpulseOrder = 0f;
					stickSwayStartTime = JackOUtility.SubsystemGameInfo.TotalElapsedGameTime;
					stickSwayStartAngle = m_stickRotation;
				}
			}
			else
			{
				float stickSwayTime = MathUtils.PI * 0.5f;
				double x = JackOUtility.SubsystemGameInfo.TotalElapsedGameTime - stickSwayStartTime;
				if (x > stickSwayTime)
				{
					m_stickRotation = 0f;
				}
				else
				{
					float fx = MathF.Cos((float)x * 6f) * stickSwayStartAngle;//stickSwayStartAngle ~ -stickSwayStartAngle
					fx *= (float)((stickSwayTime - x) / stickSwayTime);
					m_stickRotation = fx;
				}
			}
			if (ComponentJackODummy.WasHit)
			{
				hitSwayStartTime = JackOUtility.SubsystemGameInfo.TotalElapsedGameTime;
				ComponentJackODummy.WasHit = false;
			}
			double hitX = JackOUtility.SubsystemGameInfo.TotalElapsedGameTime - hitSwayStartTime;
			float hitDuration = MathUtils.PI * 0.05f;
			if (hitX > 0 && hitX <= hitDuration)
			{
				float f_hitX = MathF.Sin((float)hitX * 40f) * 0.01f;
				float f_hitX2 = MathF.Sin((float)hitX * 20f) * 0.01f;//半个周期
				m_bodyOffset = new(-f_hitX2, f_hitX2 * 0.8f, f_hitX * -1.75f);
			}
			else
			{
				m_bodyOffset = Vector3.Zero;
			}
		}

		public override void Animate()
		{
			if (ComponentSpawn != null)
			{
				Opacity = (ComponentSpawn.SpawnDuration > 0f) ? ((float)MathUtils.Saturate((JackOUtility.SubsystemGameInfo.TotalElapsedGameTime - ComponentSpawn.SpawnTime) / ComponentSpawn.SpawnDuration)) : 1f;
				if (ComponentSpawn.DespawnTime.HasValue)
				{
					Opacity = MathUtils.Min(Opacity.Value, (float)MathUtils.Saturate(1.0 - ((JackOUtility.SubsystemGameInfo.TotalElapsedGameTime - ComponentSpawn.DespawnTime.Value) / ComponentSpawn.DespawnDuration)));
				}
			}
			if (Opacity.HasValue && Opacity.Value < 1f)
			{
				bool num = ComponentJackODummy.ComponentBody.ImmersionFactor >= 1f;
				bool flag = m_subsystemSky.ViewUnderWaterDepth > 0f;
				RenderingMode = num == flag ? ModelRenderingMode.TransparentAfterWater : ModelRenderingMode.TransparentBeforeWater;
			}
			else
			{
				RenderingMode = ModelRenderingMode.AlphaThreshold;
			}
			Vector3 vector = ComponentJackODummy.ComponentBody.Rotation.ToYawPitchRoll();
			Vector3 position = ComponentJackODummy.ComponentBody.Position;
			SetBoneTransform(m_bottomBone.Index, new Matrix?(Matrix.CreateFromYawPitchRoll(vector.X, 0, 0) * Matrix.CreateTranslation(position)));
			SetBoneTransform(m_headBone.Index, new Matrix?(Matrix.CreateRotationZ(MathUtils.DegToRad(m_headRotation.X)) * Matrix.CreateRotationX(MathUtils.DegToRad(m_headRotation.Y)) * Matrix.CreateTranslation(-1.5f * m_bodyOffset.X, -2f * m_bodyOffset.Y, 2.5f * m_bodyOffset.Y) ));
			SetBoneTransform(m_hatBone.Index, new Matrix?(Matrix.CreateRotationZ(MathUtils.DegToRad(m_headRotation.X)) * Matrix.CreateRotationX(MathUtils.DegToRad(m_headRotation.Y))));
			SetBoneTransform(m_stickBone.Index, new Matrix?(Matrix.CreateRotationX(MathUtils.DegToRad(-m_stickRotation))));
			SetBoneTransform(m_bodyBone.Index, new Matrix?(Matrix.CreateRotationX(m_bodyOffset.X * 20f) * Matrix.CreateTranslation(m_bodyOffset)));
			SetBoneTransform(m_armBone.Index, new Matrix?(Matrix.CreateRotationY(m_bodyOffset.Z * 5f) * Matrix.CreateTranslation(-m_bodyOffset)));
		}

		public override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap)
		{
			base.Load(valuesDictionary, idToEntityMap);
			ComponentJackODummy = Entity.FindComponent<ComponentJackODummy>(throwOnError: true);
			ComponentSpawn = Entity.FindComponent<ComponentSpawn>();
		}

		public override void SetModel(Model model)
		{
			base.SetModel(model);
			if (Model != null)
			{
				m_bottomBone = Model.FindBone("Bottom");
				m_stickBone = Model.FindBone("Stick");
				m_bodyBone = Model.FindBone("Body");
				m_armBone = Model.FindBone("Arm");
				m_headBone = Model.FindBone("Head");
				m_hatBone = Model.FindBone("Hat");
			}
		}

	}
}
